﻿//using System;

//namespace ModbusTcp
//{
//    class Program
//    {
//        static async Task Main(string[] args)
//        {
//            var modbusClient = new ModbusTcpClient("127.0.0.1", 502);

//            modbusClient.OnLog += Console.WriteLine;

//            modbusClient.Start();

//            Console.WriteLine("Press 'q' to quit.");
//            while (Console.ReadKey().Key != ConsoleKey.Q)
//            {
//            }

//            modbusClient.Stop();
//        }
//    }
//}

using System;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
using NModbus;
using SqlSugar.TDengine;
using SqlSugar;
using TDengine.TMQ;
using System.Data;
using Newtonsoft.Json;
using System.Collections.Concurrent;
using System.IO.Ports;

class ModbusTcpClient
{
    private string _ipAddress;
    private int _port;
    private TcpClient _tcpClient;
    private IModbusMaster _modbusMaster;
    private CancellationTokenSource _cancellationTokenSource;
    private int _scanInterval;

    public ModbusTcpClient(string ipAddress, int port, int scanInterval = 1000)
    {
        _ipAddress = ipAddress;
        _port = port;
        _scanInterval = scanInterval;
    }

    public async Task StartAsync()
    {
        _cancellationTokenSource = new CancellationTokenSource();
        await ConnectAsync();

        Task.Run(() => PeriodicScan(_cancellationTokenSource.Token));
    }

    private async Task ConnectAsync()
    {
        try
        {
            _tcpClient = new TcpClient();
            await _tcpClient.ConnectAsync(_ipAddress, _port);

            var factory = new ModbusFactory();
            _modbusMaster = factory.CreateMaster(_tcpClient);

            Console.WriteLine("Modbus TCP connected.");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Failed to connect: {ex.Message}");
            await ReconnectAsync();
        }
    }

    private async Task ReconnectAsync()
    {
        Console.WriteLine("Attempting to reconnect...");
        while (!_cancellationTokenSource.Token.IsCancellationRequested)
        {
            try
            {
                await ConnectAsync();
                if (_tcpClient.Connected) break;
            }
            catch
            {
                await Task.Delay(5000);
            }
        }
    }

    private async Task PeriodicScan(CancellationToken token)
    {
        while (!token.IsCancellationRequested)
        {
            if (_tcpClient.Connected)
            {
                try
                {
                    // Example: Reading holding registers
                    ushort startAddress = 0;
                    ushort numberOfPoints = 10;
                    ushort[] registers = _modbusMaster.ReadHoldingRegisters(1, startAddress, numberOfPoints);

                    Console.WriteLine("Data Read:");
                    for (int i = 0; i < registers.Length; i++)
                    {
                        Console.WriteLine($"Register {startAddress + i}: {registers[i]}");
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Error during scan: {ex.Message}");
                }
            }
            else
            {
                await ReconnectAsync();
            }

            await Task.Delay(_scanInterval);
        }
    }

    public void Stop()
    {
        _cancellationTokenSource?.Cancel();
        _tcpClient?.Close();
        Console.WriteLine("Modbus TCP client stopped.");
    }

    public bool IsConnected => _tcpClient?.Connected ?? false;

    //static async Task Main(string[] args)
    //{
    //    var modbusClient = new ModbusTcpClient("127.0.0.1", 502, 2000);
    //    await modbusClient.StartAsync();

    //    Console.WriteLine("Press any key to stop...");
    //    Console.ReadKey();
    //    modbusClient.Stop();
    //}

    //static async Task Main(string[] args)
    //{
    //    //程序启动时加入（这个只要执行一次）
    //    InstanceFactory.CustomAssemblies =
    //        new System.Reflection.Assembly[] { typeof(TDengineProvider).Assembly };

    //    //创建 db对象    
    //    var db = new SqlSugarClient(new ConnectionConfig()
    //    {
    //        DbType = SqlSugar.DbType.TDengine,
    //        ConnectionString = "Host=localhost;Port=6030;Username=root;Password=taosdata;Database=power",
    //        IsAutoCloseConnection = true,
    //  ConfigureExternalServices = new ConfigureExternalServices()
    //  {
    //      EntityService = (property, column) =>
    //      {
    //          //if (column.SqlParameterDbType == null)
    //          //{
    //          //    //需要给列加上通用转换，这样实体就不需要一个一个转了 
    //          //    column.SqlParameterDbType = typeof(CommonPropertyConvert);
    //          //}
    //      }
    //  }
    //    });

    //    //建库
    //    db.Ado.ExecuteCommand("CREATE DATABASE IF NOT EXISTS power WAL_RETENTION_PERIOD 3600");

    //    //建超级表
    //    db.Ado.ExecuteCommand("CREATE STABLE IF NOT EXISTS  MyTable (ts TIMESTAMP, current FLOAT, voltage INT, phase FLOAT) TAGS (location BINARY(64), groupId INT)");

    //    //创建子表
    //    db.Ado.ExecuteCommand(@"create table IF NOT EXISTS  MyTable01 using MyTable tags('California.SanFrancisco',1)");


    //    //insert sql
    //    //db.Ado.ExecuteCommand(insrtSql);

    //    //查询子表
    //    var dt = db.Ado.GetDataTable("select * from MyTable01");

    //    //查询超级表
    //    DataTable dt2 = db.Ado.GetDataTable("select * from MyTable");
    //    Console.WriteLine(JsonConvert.SerializeObject(dt2));
    //}

    //public class ModbusDriver
    //{
    //    private readonly Dictionary<string, TcpClient> _clients = new();
    //    private readonly Dictionary<string, IModbusMaster> _masters = new();
    //    private readonly object _lock = new();
    //    private readonly CancellationTokenSource _cancellationTokenSource = new();

    //    private readonly ConcurrentDictionary<string, List<Action<ushort[]>>> _subscribers = new();
    //    private readonly ConcurrentDictionary<string, ushort[]> _lastValues = new();

    //    public event Action<string, Exception> OnConnectionLost;
    //    public event Action<string> OnReconnected;

    //    public void Connect(string deviceId, string ip, int port)
    //    {
    //        lock (_lock)
    //        {
    //            if (_clients.ContainsKey(deviceId))
    //            {
    //                throw new InvalidOperationException($"Device {deviceId} is already connected.");
    //            }

    //            var client = new TcpClient();
    //            client.Connect(ip, port);

    //            var factory = new ModbusFactory();
    //            var master = factory.CreateMaster(client);

    //            _clients[deviceId] = client;
    //            _masters[deviceId] = master;

    //            // 启动连接监控和读取监听任务
    //            Task.Run(() => MonitorConnection(deviceId, ip, port), _cancellationTokenSource.Token);
    //            Task.Run(() => MonitorRegisters(deviceId), _cancellationTokenSource.Token);
    //        }
    //    }

    //    public void Disconnect(string deviceId)
    //    {
    //        lock (_lock)
    //        {
    //            if (!_clients.ContainsKey(deviceId)) return;

    //            _clients[deviceId].Close();
    //            _clients.Remove(deviceId);
    //            _masters.Remove(deviceId);
    //            _subscribers.TryRemove(deviceId, out _);
    //            _lastValues.TryRemove(deviceId, out _);
    //        }
    //    }

    //    public void Subscribe(string deviceId, Action<ushort[]> callback)
    //    {
    //        if (!_subscribers.ContainsKey(deviceId))
    //        {
    //            _subscribers[deviceId] = new List<Action<ushort[]>>();
    //        }
    //        _subscribers[deviceId].Add(callback);
    //    }

    //    public void Unsubscribe(string deviceId, Action<ushort[]> callback)
    //    {
    //        if (_subscribers.ContainsKey(deviceId))
    //        {
    //            _subscribers[deviceId].Remove(callback);
    //        }
    //    }

    //    public void WriteSingleRegister(string deviceId, ushort address, ushort value)
    //    {
    //        lock (_lock)
    //        {
    //            if (!_masters.ContainsKey(deviceId))
    //            {
    //                throw new InvalidOperationException($"Device {deviceId} is not connected.");
    //            }

    //            _masters[deviceId].WriteSingleRegister(1, address, value);
    //        }
    //    }

    //    public void Start()
    //    {
    //        // 额外启动逻辑
    //    }

    //    public void Stop()
    //    {
    //        lock (_lock)
    //        {
    //            _cancellationTokenSource.Cancel();

    //            foreach (var client in _clients.Values)
    //            {
    //                client.Close();
    //            }

    //            _clients.Clear();
    //            _masters.Clear();
    //            _subscribers.Clear();
    //            _lastValues.Clear();
    //        }
    //    }

    //    private async Task MonitorConnection(string deviceId, string ip, int port)
    //    {
    //        while (!_cancellationTokenSource.Token.IsCancellationRequested)
    //        {
    //            lock (_lock)
    //            {
    //                if (!_clients.ContainsKey(deviceId)) return;

    //                var client = _clients[deviceId];

    //                if (!client.Connected)
    //                {
    //                    OnConnectionLost?.Invoke(deviceId, new Exception("Connection lost"));

    //                    try
    //                    {
    //                        client.Close();
    //                        client.Connect(ip, port);
    //                        var factory = new ModbusFactory();
    //                        _masters[deviceId] = factory.CreateMaster(client);
    //                        OnReconnected?.Invoke(deviceId);
    //                    }
    //                    catch
    //                    {
    //                        Task.Delay(5000).Wait(); // Retry after delay
    //                    }
    //                }
    //            }

    //            await Task.Delay(1000);
    //        }
    //    }

    //    private async Task MonitorRegisters(string deviceId)
    //    {
    //        ushort startAddress = 0; // 假设监听的起始地址
    //        ushort count = 10; // 假设监听的寄存器数量

    //        while (!_cancellationTokenSource.Token.IsCancellationRequested)
    //        {
    //            lock (_lock)
    //            {
    //                if (!_masters.ContainsKey(deviceId)) return;

    //                try
    //                {
    //                    var values = _masters[deviceId].ReadHoldingRegisters(1, startAddress, count);

    //                    if (_lastValues.ContainsKey(deviceId))
    //                    {
    //                        var lastValues = _lastValues[deviceId];

    //                        if (!values.SequenceEqual(lastValues))
    //                        {
    //                            _lastValues[deviceId] = values;

    //                            // 发布消息给订阅者
    //                            if (_subscribers.ContainsKey(deviceId))
    //                            {
    //                                foreach (var callback in _subscribers[deviceId])
    //                                {
    //                                    callback(values);
    //                                }
    //                            }
    //                        }
    //                    }
    //                    else
    //                    {
    //                        _lastValues[deviceId] = values;

    //                        // 初次读取直接发布
    //                        if (_subscribers.ContainsKey(deviceId))
    //                        {
    //                            foreach (var callback in _subscribers[deviceId])
    //                            {
    //                                callback(values);
    //                            }
    //                        }
    //                    }
    //                }
    //                catch (Exception ex)
    //                {
    //                    OnConnectionLost?.Invoke(deviceId, ex);
    //                }
    //            }

    //            await Task.Delay(1000); // 设置监听的刷新频率
    //        }
    //    }
    //}

    static async Task Main(string[] args)
    {
        var driver = new ModbusDriver
        {
            LogInfo = msg => Console.WriteLine($"[INFO] {msg}"),
            LogError = msg => Console.WriteLine($"[ERROR] {msg}")
        };

        driver.OnConnectionLost += (deviceId, ex) => Console.WriteLine($"Device {deviceId} lost connection: {ex.Message}");
        driver.OnReconnected += deviceId => Console.WriteLine($"Device {deviceId} reconnected");

        var configs = new List<DeviceConfig>
{
    new DeviceConfig
    {
        DeviceId = "Device1",
        Protocol = "TCP",
        Ip = "127.0.0.1",
        Port = 501,
        UnitId = 1,
        StartAddress = 0,
        Count = 10,
        PollInterval = 1000,
        RetryInterval = 10000
    },
    //new DeviceConfig
    //{
    //    DeviceId = "Device2",
    //    Protocol = "RTU",
    //    PortName = "COM1",
    //    BaudRate = 9600,
    //    Parity = Parity.None,
    //    DataBits = 8,
    //    StopBits = StopBits.One,
    //    UnitId = 1,
    //    StartAddress = 0,
    //    Count = 10,
    //    PollInterval = 5000,
    //    RetryInterval = 10000,
    //    ReadTimeout = 7000,  // 动态设置
    //    WriteTimeout = 4000  // 动态设置
    //}
};
    //    var configs1 =
    //new DeviceConfig
    //{
    //    DeviceId = "Device1",
    //    Protocol = "TCP",
    //    Ip = "127.0.0.1",
    //    Port = 501,
    //    UnitId = 1,
    //    StartAddress = 0,
    //    Count = 10,
    //    PollInterval = 3000,
    //    RetryInterval = 10000
    //};

        driver.LoadConfiguration(configs);
        driver.Subscribe("Device1", values =>
        {
            Console.WriteLine($"Device1 received values: {string.Join(", ", values)}");
        });
        driver.OnDataReceived += (a, b) => { Console.WriteLine("传递出来的值为：" + String.Join(",", b)); };
        driver.Start();
        Thread.Sleep(2000);
        //driver.UpdateConfiguration(configs1);
        Thread.Sleep(20000);
        driver.Stop();
    }

   
}
